AWS Lambda からサービスアカウントで Google APIs を叩くまでにやったこと
コンサルティング部の西野です。
AWS Lambda からサービスアカウントを使用して Google APIs を叩く機会がありましたので、その手順を紹介します。
やりたいこと
G Suite ドメイン内のユーザーによって Google Drive 上に保存されたファイルの名称を AWS Lambda 経由で取得することをゴールとします。
構成図
- server-to-server (Lambda to Google API) で API をコールするためサービスアカウントを用いる
- AWS リージョンはアジアパシフィック(東京)/ ap-northeast-1 を使用
- API コール用のサービスアカウントキーを SSM Parameter Store に SecureString として保存する
- Lambda 関数のランタイムは Python 3.8
- Lambda 関数は実行のたびにサービスアカウントキーを Parameter Store から取得する(①&②)
- API コールにはgoogle-api-python-clientを使用する(③)
サービスアカウントの作成と権限の設定
サービスアカウントの作成
まずは API コールに必要なサービスアカウントを作成していきます。
以下の作業は G Suite の管理者権限を持つアカウントから実施してください。
下記のページにアクセスし、プロジェクトを作成します。
Google APIs | リソースの管理
プロジェクト名は任意のものでOKです。
つづいてこのプロジェクトにサービスアカウントを作成します。
ハンバーガーボタン(画面左上) -> APIとサービス -> 認証情報 とクリックしてください。
次の画面で 認証情報を作成 -> サービスアカウント をクリックしてください。
任意のサービスアカウント名を付与し、作成をクリックしてください。
この画面では何も入力せずに 続行 をクリックします。
この画面でも何も入力せずに 完了 をクリックしてください。
サービスアカウントキーの作成
作成したサービスアカウントの右側にペンのマークがあるので、ここをクリックします。
鍵を追加 -> 新しい鍵を作成 をクリックします。
JSON にチェックを入れた後、作成をクリックします。JSON ファイルダウンロード用のダイアログが出現しますのでそのままダウンロードしてください。 当該 JSON には API コールのためのキーが含まれていますので、流出等にご注意ください。
権限(ドメイン全体の委任)の設定
続いてサービスアカウントに対して権限(ドメイン全体の委任)を設定していきます
Google の管理コンソールへアクセスし、セキュリティをクリックしてください。
管理コンソール
画面下部のAPI 権限 -> ドメイン全体の委任を管理 をクリックしてください。
新しく追加 をクリックします。
APIのクライアント ID と OAuth スコープ(https://www.googleapis.com/auth/drive)を入力します。
※クライアント ID は先ほどダウンロードした JSON ファイルに記載されている21桁の番号です。
入力が済んだら「承認」をクリックします。
ここまで Google 上での設定は完了です。
Parameter Storeへサービスアカウントキーを保存
サービスアカウントキーを Parameter Store に保存します。
名前 | タイプ | 値 |
---|---|---|
Google-API-Credential | 完全な文字列 (SecureString) | サービスアカウント作成時にダウンロードした JSON |
IAMロールの作成
IAM ロールは Lambda 関数の実行および Parameter Store からのパラメータ取得に必要です。
事前に下記の AWS 管理ポリシーを持つ Lambda 用の IAM ロールを作成しておきます。
AWSLambdaBasicExecutionRole
AmazonSSMReadOnlyAccess
Lambda関数の作成
Google Client Library のインストール(ローカル開発環境)
Python Quickstartを参考に必要なライブラリをインストールします。
後に Lambda 関数にアップロードするため、-t
オプションを付与しインストール先をカレントディレクトリ以下にしています。
$ pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib -t ./
コード
Google Drive 上にアップロードされたファイル名を取得するためのコードです。
3つの環境変数(REGION・SUBJECT・PARAM_KEY)については後述します。
import json import os import boto3 from google.oauth2 import service_account from googleapiclient.discovery import build REGION = os.environ.get('REGION') SUBJECT = os.environ.get('SUBJECT') PARAM_KEY = os.environ.get('PARAM_KEY') SCOPES = ['https://www.googleapis.com/auth/drive'] def lambda_handler(event, context): param_value = get_parameters(PARAM_KEY) service_account_info = json.loads(param_value) credentials = service_account.Credentials.from_service_account_info( service_account_info, scopes=SCOPES) delegated_credentials = credentials.with_subject(SUBJECT) service = build('drive', 'v3', credentials=delegated_credentials, cache_discovery=False) results = service.files().list( pageSize=10, fields="nextPageToken, files(id, name)").execute() items = results.get('files', []) for item in items: print(item['name']) def get_parameters(param_key): ssm = boto3.client('ssm', region_name=REGION) response = ssm.get_parameters( Names=[ param_key, ], WithDecryption=True ) return response['Parameters'][0]['Value']
zip ファイルの作成
下記コマンドでカレントディレクトリ以下のすべてのファイルを zip ファイル化します。
※カレントディレクトリ以下には上述のコードと依存ライブラリのすべてが配置されている前提です。
$ zip -r lambda_function.zip ./*
Lambda 関数の設定
下記の設定で Lambda 関数を作成します。
- ランタイム: Python3.8
- IAMロール: 先の手順で作成した IAM ロール
- タイムアウト時間: 15秒(実行に3秒以上かかったためデフォルト値から変更)
- 環境変数
- REGION: ap-northeast-1
- SUBJECT: G Suite ドメイン内ユーザーのメールアドレス
- PARAM_KEY: Google-API-Credential
zip ファイルのアップロード
Lambda関数 -> 関数コード -> アクション ->.zip ファイルをアップロード をクリックし、先の手順で作成した zip ファイルを Lambda 関数にアップロードします。
動かしてみる
任意のテストイベントを作成し、Lambda 関数を実行してみます。
ラー油とペットの画像ファイル名をしっかり取得できました。
終わりに
このブログがほんの少しでも世界を良くできれば嬉しいです。
コンサルティング部の西野 (@xiyegen) がお送りしました。